package tjs.study.notes.dotest.proxy.javassist.hotSwapper;

import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import javassist.*;
import javassist.util.HotSwapper;
import sun.management.VMManagement;
import tjs.study.notes.dotest.TjsStudyNotesApplication;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by Nicky.Tang on 2021/9/30 4:10 下午
 *
 * @since 02.12.10
 */
public class DoTestOfHotSwapper {
    /**
     * HotSwapper需要开启jdwp，可能有以下两个问题
     * 1.执行远程命令注入（可通过ip白名单限制）
     * 2.debug模式，需要额外的程序，是否会影响性能
     */
    public static void main(String[] args) throws Exception {
        runTest();

        reloadClass();
    }

    public static void runTest() {
        Source source = new Source();
        new Thread(() -> {
            while (true) {
                System.out.println(source.hellowWorld());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void reloadClass() throws IOException, IllegalConnectorArgumentsException, NotFoundException, CannotCompileException {
        // -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
        HotSwapper hs = new HotSwapper(8000);
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get(Source.class.getName());
        // 获取方法
        CtMethod ctMethod = ctClass.getDeclaredMethod("hellowWorld");
        // 重写方法
        ctMethod.setBody("{return \"say Hellow World\";}");

        // 写入文件
        writeNewClass(ctClass);
        // 加载新的类
        System.out.println("执行HotSwapper热插拔......");
        hs.reload(Source.class.getName(), ctClass.toBytecode());
    }

    public static void writeNewClass(CtClass ctClass) throws IOException, CannotCompileException {
        FileOutputStream outputStream = new FileOutputStream(new File(TjsStudyNotesApplication.work_space+"/proxy/javassist/hotSwapper/Source.class"));
        try {
            outputStream.write(ctClass.toBytecode());
        }finally {
            outputStream.close();
        }
    }
}
